package com.xiaobai.config;

import com.alibaba.fastjson.JSON;
import com.xiaobai.common.Article;
import com.xiaobai.common.CommonMoon;
import com.xiaobai.common.DelayIntTask;
import com.xiaobai.dao.HealthInfoDao;
import com.xiaobai.pojo.HealthInfo;
import com.xiaobai.service.addition.IFreeClassroomService;
import com.xiaobai.service.addition.IHealthReportService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;

@Component
@Slf4j
public class SchedulingTask {

    private static Random random = new Random();

    @Autowired
    private HealthInfoDao healthInfoDao;

    @Autowired
    private IHealthReportService healthReportService_v2;

    @Autowired
    private IFreeClassroomService freeClassroomService;

    @Scheduled(cron = "30 55 23 * * *")//每天晚上23点55分30秒更新每日一文
    public void updateRead(){
         log.info("更新了每日一文");
         updateArticle();

    }

    static CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    public void updateArticle(){
        HttpGet httpGet = new HttpGet("https://v2.alapi.cn/api/mryw/random?token=72FlDDg3CxGCIBrG");
        String result = null;
        try (CloseableHttpResponse execute = httpClient.execute(httpGet);){
            result = EntityUtils.toString(execute.getEntity());
        } catch (IOException e) {
            e.printStackTrace();
        }
        int startIndex=result.indexOf("\"title");
        int endIndex=result.indexOf("\"cate\":");
        if (startIndex == -1) {
            return;
        }

        result=result.substring(startIndex,endIndex);

        result="{"+result+"}";

        CommonMoon.article= JSON.parseObject(result,Article.class);
    }

    @Scheduled(cron = "1 0 0 * * ?")
    public void healthReportAction() {

        log.info("事前队列长度:{}", healthReportService_v2.queueSize());
        List<Integer> list = healthReportService_v2.queueDataAndClear();
        log.info("剩余的队列内容:{}", list);

        // 获取每个小时的两个时间点
        Map<Integer, int[]> map = new HashMap<>();
        for (int i = 8; i <= 19; i++) {
            int[] arr;
            if (i == 8 || i == 19) {
                arr = getRandom(5, 55, 10);
            } else {
                arr = getRandom(0, 60, 10);
            }
            map.put(i, arr);
        }

        List<Integer> expireIds = new ArrayList<>();
        long l = System.currentTimeMillis();
        Calendar calendar = Calendar.getInstance();
        // 获取所有open任务
        List<HealthInfo> healthInfoList = healthInfoDao.getOpenIds();
        for (HealthInfo healthInfo : healthInfoList) {
            if (DateUtils.addDays(healthInfo.getCreateTime(), 15).getTime() < l) {
                expireIds.add(healthInfo.getId());
                continue;
            }
            String timingStr = healthInfo.getTimingStr();
            String[] split = timingStr.split(":");
            int hour = Integer.parseInt(split[0]);
            // 分钟不具有参考价值
            int min = Integer.parseInt(split[1]);

            // 时间已过,也不用关心,因为redis对延时队列做了支持,会将未打卡的在启动时重新放入队列中

            // 小时段打卡,集中两波打卡
            calendar.set(Calendar.HOUR_OF_DAY, hour);

            if (hour >= 12) {
                // 12点的以后才集中
                int[] ints = map.get(hour);
//                calendar.set(Calendar.MINUTE, ints[random.nextInt(ints.length)]);
                // 12点后都是少数,就直接一个点
                calendar.set(Calendar.MINUTE, ints[0]);
            } else {
                // 12点前不集中了,打完体验的20元抛弃此功能
                calendar.set(Calendar.MINUTE, min);
            }

            DelayIntTask delayIntTask = new DelayIntTask(healthInfo.getId(),calendar.getTime());
            healthReportService_v2.addDelayTask(delayIntTask);
        }
        if (expireIds.size() != 0) {
            healthInfoDao.closeActionByIds(expireIds);
        }
        log.info("有效打卡人数:{},失效人数:{}", healthInfoList.size() - expireIds.size(), expireIds.size());
        log.info("事后队列长度:{}", healthReportService_v2.queueSize());
    }

    /**
     * 获取两数字 [0~59] 并且两者不能相差10分钟以内
     */
    private int[] getRandom(int leftRange, int rightRange, int space) {
        int num1 = 0;
        int num2 = 0;
        while (Math.abs(num1 - num2) < space) {
            num1 = random.nextInt(rightRange - leftRange) + leftRange;
            num2 = random.nextInt(rightRange - leftRange) + leftRange;
        }
        return new int[]{num1, num2};
    }

    @Scheduled(cron = "30 55 8,20 * * ?")//每天晚上20点55分30秒自此再次更新明天的课程和第8天的CDN文件
    public void freeClassroom() {
        // 1656607907000L => 2022-7-2 12:51:47 放假了不更新
        long lastDay = 1656607907000L;
        Date nowDate = new Date();
        // 1645894307000L => 2022-02-27 00:51:47 还没开学不更新
        if (nowDate.getTime() > lastDay || nowDate.getTime() < 1645894307000L) {
            log.info("freeClassroom不更新了");
            return;
        }
        Date tomorrowDay = DateUtils.addDays(nowDate, 1);
        Date eigDate = DateUtils.addDays(nowDate, 8);
        Date[] arr = null;
        if (eigDate.getTime() < lastDay) {
            arr = new Date[2];
            arr[0] = tomorrowDay;
            arr[1] = eigDate;
        } else if (tomorrowDay.getTime() < lastDay) {
            arr = new Date[1];
            arr[0] = tomorrowDay;
        }
        // 更新明天和第八天
        freeClassroomService.save(arr);
    }

    // 假期在家上报, 现在停止
//    @Scheduled(cron = "30 00 10 * * ?")
//    public void ybv3() {
//        List<String> v3List = stringRedisTemplate.opsForList().range("v3List", 0, -1);
//        for (String str : v3List) {
//            HealthReportService_v3.HealthInfoV3 healthInfoV3 = JSONObject.parseObject(str, HealthReportService_v3.HealthInfoV3.class);
//            healthReportService_v3.doActionV3(healthInfoV3.getStudentId(), "Abcxyz123!", healthInfoV3, 5, false);
//        }
//    }

    public static void main(String[] args) {
        Calendar nowCalendar = Calendar.getInstance();
        System.out.println(nowCalendar.get(Calendar.HOUR_OF_DAY));
        System.out.println(nowCalendar.get(Calendar.MINUTE));
        System.out.println(DateFormatUtils.format(nowCalendar.getTime(), "HH:mm"));
    }

}
